package com.yixing.tech.common.aop.aspect;

import com.yixing.tech.common.base.BaseResponse;
import com.yixing.tech.common.base.BizOpCode;
import com.yixing.tech.common.base.BusinessException;
import com.yixing.tech.common.base.Rs;
import com.yixing.tech.common.enums.ErrCode;
import com.yixing.tech.common.utils.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.data.mongodb.UncategorizedMongoDbException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;

import java.util.Locale;

/**
 * 全局异常处理切面
 */
@Aspect
@Component
@Slf4j
public class GlobalExceptionHandlerAspect {

    @Autowired
    private MessageSource messageSource;

    @Around("@annotation(org.springframework.web.bind.annotation.RestController)")
    public Object handleException(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            return joinPoint.proceed();
        } catch (Throwable e) {
            return handleExceptionInternal(e);
        }
    }

    private Object handleExceptionInternal(Throwable e) throws Throwable {
        if (e instanceof BusinessException) {
            BusinessException be = (BusinessException) e;
            int code = be.getErrorCode();
            String message = e.getMessage();
            String defaultMsg = !CommonUtil.stringIsBlank(be.getMsg()) ? be.getMsg().toString() : message;
            String msg = messageSource.getMessage(String.valueOf(code), null, defaultMsg, Locale.getDefault());
            return Rs.fail(msg);
        } else if (e instanceof UsernameNotFoundException) {
            return Rs.fail("账号不存在或密码不正确！");
        } else if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException)e;
            BindingResult bindingResult = ex.getBindingResult();
            String message = bindingResult.getFieldError() != null ?
                bindingResult.getFieldError().getDefaultMessage() :
                "参数校验失败";
            log.error(message, e);
            return Rs.fail(message);
        } else if (e instanceof MissingServletRequestParameterException) {
            String message = e.getMessage();
            log.error(message, e);
            return Rs.fail(message);
        } else if(e instanceof UncategorizedMongoDbException){
            String message = e.getMessage();
            log.error(message, e);
            return Rs.fail(BizOpCode.INTERNAL_SERVER_ERROR, message);
        }  else if(e instanceof RuntimeException){
            throw e;
        }else {
            log.error("error", e);
            return Rs.fail("系统错误");
        }
    }
}
